1.17 Error Handling in C Programming

Module 1.17 • Syntax Validation, Error Streams, errno Maps & Long Jumps Recovery

1.17.1 Introduction

No program is perfect. During execution, unexpected situations may occur such as invalid input, memory allocation failures, file access problems, or incorrect calculations.

The process of identifying, managing, and responding to such situations is called Error Handling.

Proper error handling helps:

Unlike some modern programming languages, C does not provide built-in exception handling mechanisms like try-catch blocks. Therefore, programmers must manually detect and handle errors.

1.17.2 What is an Error?

An error is a condition that prevents a program from working as expected.

Example:

int result = 10 / 0;

This causes a runtime error because division by zero is not allowed.

1.17.3 Categories of Errors in C

Errors are generally divided into three groups:

  1. Syntax Errors
  2. Runtime Errors
  3. Logical Errors

1.17.4 Syntax Errors

Syntax errors occur when program statements do not follow C language rules. These errors are detected during compilation.

Example

#include<stdio.h>
 
int main()
{
    printf("Welcome")
    return 0;
}

Error: Missing semicolon (;)

Correct Version:

printf("Welcome");

Common Syntax Errors

Example:

pritnf("Hello");

Compiler Error: Undefined function

1.17.5 Runtime Errors

Runtime errors occur while the program is executing. The compiler cannot detect these errors.

Examples

Example: Division by Zero

#include<stdio.h>
 
int main()
{
    int a = 50;
    int b = 0;
 
    printf("%d", a / b);
 
    return 0;
}

Result: Runtime Error

Example: Invalid Pointer Access

int *ptr = NULL;
 
printf("%d", *ptr);

Result: Segmentation Fault

1.17.6 Logical Errors

Logical errors occur when the program runs successfully but produces incorrect results. These are usually the most difficult errors to find.

Example

#include<stdio.h>
 
int main()
{
    int length = 12;
    int width = 8;
 
    int area;
 
    area = length + width;
 
    printf("%d", area);
 
    return 0;
}

Output: 20

Correct Formula: area = length * width;

Expected Output: 96

1.17.7 Error Handling Techniques in C

Common techniques include:

  1. Return Values
  2. Error Codes
  3. errno
  4. perror()
  5. assert()
  6. setjmp() and longjmp()

1.17.8 Using Return Values

Many functions return values indicating success or failure.

Example: int status;

Possible values:

0  -> Success
-1 -> Failure

Example Program

#include<stdio.h>
 
int divide(int x,int y)
{
    if(y == 0)
        return -1;
 
    return x / y;
}
 
int main()
{
    int result;
 
    result = divide(40,0);
 
    if(result == -1)
        printf("Division Error");
 
    return 0;
}

Output: Division Error

1.17.9 Custom Error Codes

Programmers often define their own error codes.

Example:

#define SUCCESS 0
#define FILE_ERROR 1
#define MEMORY_ERROR 2
#define INPUT_ERROR 3

Example

#include<stdio.h>
 
#define SUCCESS 0
#define INPUT_ERROR 1
 
int main()
{
    int age;
 
    printf("Enter Age: ");
 
    if(scanf("%d",&age) != 1)
    {
        return INPUT_ERROR;
    }
 
    return SUCCESS;
}

1.17.10 Checking Memory Allocation Errors

Always verify memory allocation.

Bad Practice:

int *ptr;
 
ptr = malloc(100*sizeof(int));

Good Practice:

int *ptr;
 
ptr = malloc(100*sizeof(int));
 
if(ptr == NULL)
{
    printf("Memory Allocation Failed");
}

Example Program

#include<stdio.h>
#include<stdlib.h>
 
int main()
{
    int *ptr;
 
    ptr = malloc(500000000*sizeof(int));
 
    if(ptr == NULL)
    {
        printf("Unable to Allocate Memory");
        return 1;
    }
 
    printf("Memory Allocated Successfully");
 
    free(ptr);
 
    return 0;
}

1.17.11 Handling File Errors

File operations frequently generate errors.

Example: FILE *fp; fp = fopen("report.txt","r");

If the file does not exist: fp = NULL

Correct Handling

if(fp == NULL)
{
    printf("File Cannot Be Opened");
}

Example Program

#include<stdio.h>
 
int main()
{
    FILE *fp;
 
    fp = fopen("sales.txt","r");
 
    if(fp == NULL)
    {
        printf("File Not Found");
        return 1;
    }
 
    fclose(fp);
 
    return 0;
}

1.17.12 The errno Variable

C provides a global variable called: errno. It stores system error information.

Required Header: #include <errno.h>

Example Program

#include<stdio.h>
#include<errno.h>
 
int main()
{
    FILE *fp;
 
    fp = fopen("missing.txt","r");
 
    if(fp == NULL)
    {
        printf("Error Code = %d", errno);
    }
 
    return 0;
}

Output may vary: Error Code = 2

1.17.13 perror() Function

perror() displays a human-readable description of the current error.

Syntax:

perror("message");

Example

#include<stdio.h>
 
int main()
{
    FILE *fp;
 
    fp = fopen("unknown.txt","r");
 
    if(fp == NULL)
    {
        perror("File Error");
    }
 
    return 0;
}

Possible Output: File Error: No such file or directory

1.17.14 strerror() Function

Converts an error number into readable text.

Required Header: #include<string.h>, #include<errno.h>

Example: printf("%s", strerror(errno));

Output Example: No such file or directory

1.17.15 Using assert()

The assert macro helps detect programming mistakes during development.

Header File: #include<assert.h>

Example

#include<stdio.h>
#include<assert.h>
 
int main()
{
    int quantity = 0;
 
    assert(quantity > 0);
 
    return 0;
}

Result: Program Terminated, Assertion Failed

Why Use assert()?

Useful for:

Example of assert()

#include<stdio.h>
#include<assert.h>
 
int main()
{
    int marks = 85;
 
    assert(marks >= 0);
 
    printf("Valid Marks");
 
    return 0;
}

Output: Valid Marks

1.17.17 setjmp() and longjmp()

These functions provide a mechanism similar to exception handling.

Required Header: #include<setjmp.h>

Functions: setjmp(), longjmp()

How They Work

Step 1: setjmp() saves the program state.

Step 2: longjmp() returns execution to that saved state.

Example Program

#include<stdio.h>
#include<setjmp.h>
 
jmp_buf buffer;
 
void test()
{
    printf("Error Occurred\n");
 
    longjmp(buffer,1);
}
 
int main()
{
    if(setjmp(buffer))
    {
        printf("Returned After Error");
        return 0;
    }
 
    test();
 
    return 0;
}

Output:

Error Occurred
Returned After Error

1.17.19 Resource Clean up

Whenever an error occurs, resources should be released. Resources include:

Example

FILE *fp;
 
fp = fopen("data.txt","r");
 
if(fp == NULL)
{
    return 1;
}
 
fclose(fp);

Always close files after use.

1.17.20 Error Logging

Many applications maintain logs.

Example: fprintf(logFile, "Invalid Login Attempt\n");

Benefits:

1.17.21 Defensive Programming

Defensive programming means anticipating possible failures before they occur.

Example: if(ptr != NULL) { free(ptr); }, Instead of: free(ptr);

1.17.22 Common Programming Errors

Division by Zero

num / 0

Invalid Memory Access

*NULL

Using Uninitialized Variables

int x; printf("%d",x);

Array Overflow

int arr[5]; arr[10] = 25;

Double Free

free(ptr); free(ptr);

1.17.23 Best Practices

1.17.24 Error Handling Workflow

Program Starts
       |
       v
Perform Operation
       |
       v
Error Occurred?
   /       \
 Yes        No
  |         |
Handle     Continue
Error      Execution
  |
Release Resources
  |
Display Message
  |
Continue / Exit

1.17.25 Advantages of Proper Error Handling

Summary

Verify Comprehension: Technical Knowledge Assessment

Click your choice for each question to view feedback immediately. Complete all questions to evaluate your metric score.